package com.ly.heart.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Optional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.ly.common.PageParam;
import com.ly.common.annotation.DataScope;
import com.ly.common.core.domain.AjaxResult;
import com.ly.common.exception.CustomException;
import com.ly.common.utils.DateUtils;
import com.ly.common.utils.SecurityUtils;
import com.ly.common.utils.StringUtils;
import com.ly.common.utils.erp.CommonUtil;
import com.ly.common.utils.erp.ConstUtil;
import com.ly.common.utils.erp.SnowflakeIdWorker;
import com.ly.heart.domain.ActTaskCommentEntity;
import com.ly.heart.domain.KingBankAccountEntity;
import com.ly.heart.domain.KingFinanceTransferReceiptDetailEntity;
import com.ly.heart.domain.dto.KingFinanceTransferReceiptDto;
import com.ly.heart.domain.dto.StartProcessDto;
import com.ly.common.core.domain.ActCurrentTaskVo;
import com.ly.heart.domain.vo.KingFinanceTransferReceiptVo;
import com.ly.heart.mapper.KingFinanceTransferReceiptDetailsMapper;
import com.ly.heart.mapper.KingFinanceTransferReceiptMapper;
import com.ly.heart.service.IActModelService;
import com.ly.heart.service.IActTaskCommentService;
import com.ly.heart.service.IKingBankAccountService;
import com.ly.heart.service.IKingFinanceTransferReceiptService;
import com.ly.heart.service.king.TransferReceiptPushService;
import com.ly.heart.util.CurrentUserUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.ly.heart.domain.KingFinanceTransferReceiptEntity;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;

/**
 * 金蝶-财务-银行转账单Service业务层处理
 * @author wutao
 * @date 2024-06-20
 */
@Slf4j
@Service
public class KingFinanceTransferReceiptServiceImpl extends ServiceImpl<KingFinanceTransferReceiptMapper, KingFinanceTransferReceiptEntity> implements IKingFinanceTransferReceiptService {

    @Resource
    private KingFinanceTransferReceiptMapper kingFinanceTransferReceiptEntityMapper;
    @Resource
    private KingFinanceTransferReceiptDetailsMapper kingFinanceTransferReceiptDetailsMapper;
    @Resource
    private IActModelService iActModelService;
    @Resource
    private IActTaskCommentService iActTaskCommentService;
    @Resource
    private IKingBankAccountService iKingBankAccountService;
    @Resource
    private TransferReceiptPushService transferReceiptPushService;

    /**
     * 查询金蝶-财务-银行转账单
     * @param id 金蝶-财务-银行转账单ID
     * @return 金蝶-财务-银行转账单
     */
    @Override
    public KingFinanceTransferReceiptVo selectKingFinanceTransferReceiptEntityById (String id) {
        KingFinanceTransferReceiptEntity kingFinanceTransferReceiptEntity = kingFinanceTransferReceiptEntityMapper.selectKingFinanceTransferReceiptEntityById ( id );
        KingFinanceTransferReceiptDetailEntity transferReceiptDetailEntity = new KingFinanceTransferReceiptDetailEntity ();
        transferReceiptDetailEntity.setTransferReceiptId ( id );
        List<KingFinanceTransferReceiptDetailEntity> transferReceiptDetailEntities = kingFinanceTransferReceiptDetailsMapper.selectTransferList ( transferReceiptDetailEntity );
        KingFinanceTransferReceiptVo kingFinanceTransferReceiptVo = new KingFinanceTransferReceiptVo ();
        kingFinanceTransferReceiptVo.setKingFinanceTransferReceiptEntity ( kingFinanceTransferReceiptEntity ).setKingFinanceTransferReceiptDetailEntities ( transferReceiptDetailEntities );
        return kingFinanceTransferReceiptVo;
    }

    /**
     * 查询金蝶-财务-银行转账单列表
     * @param kingFinanceTransferReceiptEntity 金蝶-财务-银行转账单
     * @return 金蝶-财务-银行转账单
     */
    @Override
    @DataScope (deptAlias = "sd")
    public AjaxResult selectKingFinanceTransferReceiptEntityList (KingFinanceTransferReceiptEntity kingFinanceTransferReceiptEntity) {
        kingFinanceTransferReceiptEntity.setPage ( ( kingFinanceTransferReceiptEntity.getPage () - 1 ) * kingFinanceTransferReceiptEntity.getLimit () );
        kingFinanceTransferReceiptEntity.setIsUsed ( ConstUtil.IS_USED_YES );
        List<KingFinanceTransferReceiptEntity> kingFinanceTransferReceiptEntities = kingFinanceTransferReceiptEntityMapper.selectKingFinanceTransferReceiptList ( kingFinanceTransferReceiptEntity );
        //根据是否到期，给出不同提示；当日日期是否大于等于到期日，给出提示
        for ( KingFinanceTransferReceiptEntity vo : kingFinanceTransferReceiptEntities ) {
            // 根据当前时间计算是否交货逾期，根据项目状态是否已完成，如果已完成的项目不参与计算是否逾期
            if ( ! ObjectUtils.isEmpty ( vo.getDueDate () ) ) {
                int day = CommonUtil.timeDifferenceDay ( new Date (), vo.getDueDate () );
                // day大于0表示正常，小于0，为逾期，值为逾期天数
                vo.setExpireDay ( day );
            }
            //处理最后一个审批人
            ActTaskCommentEntity actTaskCommentEntity = iActTaskCommentService.queryLastComment ( vo.getInstanceId () );
            if ( actTaskCommentEntity != null ) {
                vo.setApprovedUser ( actTaskCommentEntity.getApprovedUser () );
                vo.setApprovedRemark ( actTaskCommentEntity.getRemark () );
            }
            //任务信息
            ActCurrentTaskVo currentTaskVo = iActModelService.getCurrentTaskByInstanceId ( vo.getInstanceId () );
            Optional.ofNullable ( currentTaskVo ).ifPresent ( currentTask -> {
                vo.setCurrentTask ( currentTask );
            } );
        }
        Integer integer = kingFinanceTransferReceiptEntityMapper.selectKingFinanceTransferReceiptCount ( kingFinanceTransferReceiptEntity );
        PageParam p = new PageParam ();
        p.setRecords ( kingFinanceTransferReceiptEntities ).setTotal ( integer );
        return AjaxResult.success ( p );
    }

    /**
     * 新增金蝶-财务-银行转账单
     * 检查支出账户的余额是否够付款
     * @param kingFinanceTransferReceiptDto 金蝶-财务-银行转账单
     * @return 结果
     */
    @Override
    @Transactional ( rollbackFor = Exception.class, propagation = Propagation.REQUIRED )
    public AjaxResult draft (KingFinanceTransferReceiptDto kingFinanceTransferReceiptDto) {
        KingFinanceTransferReceiptEntity kingFinanceTransferReceiptEntity = kingFinanceTransferReceiptDto.getKingFinanceTransferReceiptEntity ();
        kingFinanceTransferReceiptEntity.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
        int count = this.count ();
        kingFinanceTransferReceiptEntity.setBillNo ( "YHZZD".concat ( String.format ( "%08d", count ) ) );
        if ( StringUtils.isBlank ( kingFinanceTransferReceiptEntity.getTransferInAmount () ) ) {
            return AjaxResult.error ( "转入金额不能为空！" );
        }
        //检查支出账户的余额可够支出
        List<KingFinanceTransferReceiptDetailEntity> receiptDetailEntities = kingFinanceTransferReceiptDto.getKingFinanceTransferReceiptDetailEntities ();
        receiptDetailEntities.forEach ( detail -> {
            KingBankAccountEntity one = iKingBankAccountService.getOne ( new LambdaQueryWrapper<KingBankAccountEntity> ().eq ( KingBankAccountEntity :: getBankCode, detail.getOutBankCode () ) );
            if ( one != null ) {
                if ( Double.parseDouble ( StringUtils.isBlank ( detail.getTransferOutAmount () ) ? "0" : detail.getTransferOutAmount () ) > Double.parseDouble ( StringUtils.isBlank ( one.getOpeningBalance () ) ? "0" : one.getOpeningBalance () ) ) {
                    throw new CustomException ( "【" + detail.getOutBankCode () + "】的银行账号余额不够，不能付款" );
                }
            }
        } );
        //天数（到期日-业务日期=天数）
        int days = CommonUtil.timeDifferenceDay ( kingFinanceTransferReceiptEntity.getBusinessTime (), kingFinanceTransferReceiptEntity.getDueDate () );
        //计算利息金额=转入金额*利率/365*天数
        double amount = Double.parseDouble ( kingFinanceTransferReceiptEntity.getTransferInAmount () );
        double rate = Double.parseDouble ( kingFinanceTransferReceiptEntity.getRate () ) / 100;
        double r = amount * rate / 365 * days;
        String interest = CommonUtil.doublePoint ( r, 2 );
        kingFinanceTransferReceiptEntity.setInterestMoney ( interest );
        kingFinanceTransferReceiptEntity.setCreateBy ( StringUtils.isNoneBlank ( kingFinanceTransferReceiptEntity.getCreateBy () ) ? kingFinanceTransferReceiptEntity.getCreateBy () : SecurityUtils.getLoginUser ().getUser ().getUserId () );
        kingFinanceTransferReceiptEntity.setCreateTime ( DateUtils.getNowDate () );
        kingFinanceTransferReceiptEntity.setUserId ( StringUtils.isNoneBlank ( kingFinanceTransferReceiptEntity.getCreateBy () ) ? kingFinanceTransferReceiptEntity.getCreateBy () : SecurityUtils.getLoginUser ().getUser ().getUserId () );
        kingFinanceTransferReceiptEntity.setDeptId ( CurrentUserUtil.getCompanyId () );
        List<KingFinanceTransferReceiptDetailEntity> transferReceiptDetailEntities = kingFinanceTransferReceiptDto.getKingFinanceTransferReceiptDetailEntities ();
        int insert = updateTransferDetail ( transferReceiptDetailEntities, kingFinanceTransferReceiptEntity.getId () );
        if ( insert == 0 ) {
            return AjaxResult.error ( "新增银行转账单明细清单失败！" );
        }
        kingFinanceTransferReceiptEntity.setState ( ConstUtil.STATE_IN_DRAFT );
        boolean save = this.save ( kingFinanceTransferReceiptEntity );
        if ( ! save ) {
            throw new CustomException ( "暂存银行转账单失败！" );
        }
        return AjaxResult.success ( "暂存银行转账单成功", kingFinanceTransferReceiptEntity.getId () );
    }

    @Override
    public AjaxResult submit (KingFinanceTransferReceiptEntity kingFinanceTransferReceiptEntity) {
        if ( StringUtils.isBlank ( kingFinanceTransferReceiptEntity.getId () ) ) {
            return AjaxResult.error ( "请先暂存该单据！" );
        }
        StartProcessDto startDto = new StartProcessDto ().
                setBusinessId ( kingFinanceTransferReceiptEntity.getId () ).
                setBusinessType ( kingFinanceTransferReceiptEntity.getBusinessType () ).setModelId ( kingFinanceTransferReceiptEntity.getModelId () ).
                setBusinessName ( "银行转账单_".concat ( kingFinanceTransferReceiptEntity.getId () ) );
        String instanceId = iActModelService.startProcess ( startDto );
        boolean update = this.update ( new LambdaUpdateWrapper<KingFinanceTransferReceiptEntity> ().
                set ( KingFinanceTransferReceiptEntity :: getInstanceId, instanceId ).
                set ( KingFinanceTransferReceiptEntity :: getState, ConstUtil.STATE_IN_PROCESS ).
                eq ( KingFinanceTransferReceiptEntity :: getId, kingFinanceTransferReceiptEntity.getId () ) );
        if ( ! update ) {
            throw new CustomException ( "提交银行转账单失败！" );
        }
        return AjaxResult.success ();
    }

    /**
     * 银行转账单审批完成后业务
     * 1、修改审批状态
     * 2、处理银行期初余额
     * 3、推送金蝶
     * @param kingFinanceTransferReceiptEntity
     * @return
     */
    @Override
    @Transactional ( rollbackFor = Exception.class, propagation = Propagation.REQUIRED )
    public AjaxResult approve (KingFinanceTransferReceiptEntity kingFinanceTransferReceiptEntity) {
        int i = kingFinanceTransferReceiptEntityMapper.updateById ( kingFinanceTransferReceiptEntity );
        if ( i == 0 ) {
            throw new CustomException ( "修改审批状态失败！" );
        }
        KingFinanceTransferReceiptDetailEntity transferReceiptDetailEntity = new KingFinanceTransferReceiptDetailEntity ();
        transferReceiptDetailEntity.setTransferReceiptId ( kingFinanceTransferReceiptEntity.getId () );
        List<KingFinanceTransferReceiptDetailEntity> transferReceiptDetailEntities = kingFinanceTransferReceiptDetailsMapper.selectTransferList ( transferReceiptDetailEntity );
        if ( CollectionUtils.isEmpty ( transferReceiptDetailEntities ) ) {
            return AjaxResult.success ();
        }
        transferReceiptDetailEntities.forEach ( detail -> {
            KingBankAccountEntity in = iKingBankAccountService.getOne ( new LambdaQueryWrapper<KingBankAccountEntity> ().eq ( KingBankAccountEntity :: getBankCode, detail.getInBankCode () ) );
            log.info ( "-1--> {}", in );
            KingBankAccountEntity out = iKingBankAccountService.getOne ( new LambdaQueryWrapper<KingBankAccountEntity> ().eq ( KingBankAccountEntity :: getBankCode, detail.getOutBankCode () ) );
            log.info ( "-2--> {}", out );
            String inMoney = CommonUtil.sumStr ( in.getOpeningBalance (), detail.getTransferInAmount (), 2 ); // 计算后的期初余额
            log.info ( "-3--> {}", inMoney );
            String outMoney = CommonUtil.subStr ( out.getOpeningBalance (), detail.getTransferOutAmount (), 2 ); // 计算后的期初余额
            log.info ( "-4--> {}", outMoney );
            boolean inUpdate = iKingBankAccountService.update ( new LambdaUpdateWrapper<KingBankAccountEntity> ().set ( KingBankAccountEntity :: getOpeningBalance, inMoney ).eq ( KingBankAccountEntity :: getBankCode, in.getBankCode () ) );
            log.info ( "-5--> {}", inUpdate );
            boolean outUpdate = iKingBankAccountService.update ( new LambdaUpdateWrapper<KingBankAccountEntity> ().set ( KingBankAccountEntity :: getOpeningBalance, outMoney ).eq ( KingBankAccountEntity :: getBankCode, out.getBankCode () ) );
            log.info ( "-6--> {}", outUpdate );
            if ( ! inUpdate || ! outUpdate ) {
                throw new CustomException ( "账户期初余额变更失败！" );
            }
        } );
        transferReceiptPushService.push ( kingFinanceTransferReceiptEntity );
        return AjaxResult.success ();
    }


    /**
     * 修改金蝶-财务-银行转账单
     * @param kingFinanceTransferReceiptDto 金蝶-财务-银行转账单
     * @return 结果
     */
    @Override
    public AjaxResult updateKingFinanceTransferReceiptEntity (KingFinanceTransferReceiptDto kingFinanceTransferReceiptDto) {
        KingFinanceTransferReceiptEntity kingFinanceTransferReceiptEntity = kingFinanceTransferReceiptDto.getKingFinanceTransferReceiptEntity ();
        kingFinanceTransferReceiptEntity.setUpdateBy ( SecurityUtils.getLoginUser ().getUser ().getUserId () );
        kingFinanceTransferReceiptEntity.setUpdateTime ( DateUtils.getNowDate () );
        int insert = updateTransferDetail ( kingFinanceTransferReceiptDto.getKingFinanceTransferReceiptDetailEntities (), kingFinanceTransferReceiptEntity.getId () );
        if ( insert == 0 ) {
            return AjaxResult.error ( "新增银行转账单明细清单失败！" );
        }
        boolean b = this.updateById ( kingFinanceTransferReceiptEntity );
        if ( ! b ) {
            throw new CustomException ( "修改银行转账单失败！" );
        }
        return AjaxResult.success ();
    }

    /**
     * 批量删除金蝶-财务-银行转账单
     * @param ids 需要删除的金蝶-财务-银行转账单ID
     * @return 结果
     */
    @Override
    public AjaxResult deleteKingFinanceTransferReceiptEntityByIds (String[] ids) {
        boolean update = this.update ( new LambdaUpdateWrapper<KingFinanceTransferReceiptEntity> ().set ( KingFinanceTransferReceiptEntity :: getIsUsed, ConstUtil.IS_USED_NO ).in ( KingFinanceTransferReceiptEntity :: getId, ids ) );
        if ( ! update ) {
            throw new CustomException ( "删除银行转账单失败！" );
        }
        return AjaxResult.success ();
    }

    /**
     * 更新银行转账单里明细清单
     * @param kingFinanceTransferReceiptDetailEntities
     * @param transferReceiptId
     * @return
     */
    private int updateTransferDetail (List<KingFinanceTransferReceiptDetailEntity> kingFinanceTransferReceiptDetailEntities, String transferReceiptId) {
        if ( ! CollectionUtils.isEmpty ( kingFinanceTransferReceiptDetailEntities ) ) {
            KingFinanceTransferReceiptDetailEntity transferReceiptDetailEntity = new KingFinanceTransferReceiptDetailEntity ();
            transferReceiptDetailEntity.setTransferReceiptId ( transferReceiptId );
            kingFinanceTransferReceiptDetailsMapper.deleteTransfer ( transferReceiptDetailEntity );
            kingFinanceTransferReceiptDetailEntities.forEach ( kingFinanceTransferReceiptDetailEntity -> {
                kingFinanceTransferReceiptDetailEntity.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
                kingFinanceTransferReceiptDetailEntity.setTransferReceiptId ( transferReceiptId );
                kingFinanceTransferReceiptDetailEntity.setCreateBy ( StringUtils.isNoneBlank ( kingFinanceTransferReceiptDetailEntity.getCreateBy () ) ? kingFinanceTransferReceiptDetailEntity.getCreateBy () : SecurityUtils.getLoginUser ().getUser ().getUserId () );
                kingFinanceTransferReceiptDetailEntity.setCreateTime ( DateUtils.getNowDate () );
                int insert = kingFinanceTransferReceiptDetailsMapper.insertTransfer ( kingFinanceTransferReceiptDetailEntity );
                if ( insert == 0 ) {
                    throw new RuntimeException ( "更新银行转账单明细清单失败！" );
                }
            } );
        }
        return 1;
    }

}
